Combino dos archivos, uno de formato csv y otro xls. Se limpian los datos y se elige una muestra de datos, para explorar la relación entre variables. Se contruyen tablas auxiliares para realizar un análisis de la información de la tabla en su totalidad. Primero hago una revisión del comportamiento de los datos para un año y posterioremente para una muestra de más años.
Algunas preguntas que se pueden hacer son:
Los datos que se usan son correspondientes a las tasas de participación laboral por género y la tasa de informalidad laboral. Para mayor detalle se puede consultar la descripción desde las siguiente fuentes:
In [1]:
#Se cargan las librerías requeridas
%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
from __future__ import division
plt.style.use('ggplot')
plt.rcParams['figure.figsize']=(20,7)
In [2]:
#Se carga el primer archivo, la informacion es la población en trabajos informales por estado y año
Informalidad=pd.read_excel('/home/dlegorreta/Documentos/Tutorial-Python/Datos/Base_Tasa_de_informalidad.xlsx')
In [3]:
#Se cargan los datos sobre la brecha laboral
Brecha=pd.read_csv('/home/dlegorreta/Documentos/Tutorial-Python/Datos/Base_Brecha_entre_la_TNP_femenina_y_TNP_masculina.csv')
In [4]:
#Se visualiza los primeros registros para las dos tablas
Informalidad.head()
Out[4]:
In [5]:
Brecha.head()
Out[5]:
Se aprecia que la tabla "Brecha" cuenta con datos ND, pero antes de limpiar el archivo o quitar los missing data, exploro el tipo de datos de cada columna.
In [6]:
Informalidad.info()
In [7]:
Brecha.info()
Además de ver los tipo de datos, lo titulos de la tabla "Brecha" son muy largos, para facilitar el tratamiento de los datos cambio los nombres de las variables o columnas. Los títulos de la tabla "informalidad" también los cambio por algo más breve.
In [8]:
Brecha.columns=['Periodo','Entidad','Grupo_Edad','PEA_M','PET_M','TNP_M','PEA_H','PET_H','TNP_H']
Informalidad.columns=['Periodo','Entidad','Sexo','Grupo_Edad','TAgroInf','TSecInf','TInfSecFor','TDomesInf','Pob_Ocup_T']
In [9]:
Brecha.head()
Out[9]:
In [10]:
Informalidad.head()
Out[10]:
El tipo de datos como se cargan los datos por medio de Pandas se visualiza con el sigueinte comando:
Brecha.info()
Se observa que en el entorno de trabajo, el tipo 'object', que son algo así como tipo 'string' en un contexto de bases de datos o sql. Así que para poder procesar la información hago el cambio a tipo de datos numérico. En la tabla "Informalidad" no hago ningún cambio, los datos quedan cargados con el tipo de datos que se requiere para el análisis.
In [11]:
#Cambio el tipo de datos a numérico
Brecha['PEA_M']=pd.to_numeric(Brecha['PEA_M'],errors='coercion')
Brecha['PET_M']=pd.to_numeric(Brecha['PET_M'],errors='coercion')
Brecha['TNP_M']=pd.to_numeric(Brecha['TNP_M'],errors='coercion')
Brecha['PEA_H']=pd.to_numeric(Brecha['PEA_H'],errors='coercion')
Brecha['PET_H']=pd.to_numeric(Brecha['PET_H'],errors='coercion')
Brecha['TNP_H']=pd.to_numeric(Brecha['TNP_H'],errors='coercion')
In [12]:
#Reviso el nuevo tipo de dato
Brecha.info()
In [13]:
#Se visualizan de nuevo los primeros 5 registros de los datos
Brecha.head()
Out[13]:
Ahora el problema que se presenta al observar los datos son los registros "NaN", lo que hago es primero conocer la cantidad de registros que se tienen y después se "limpia" el DataFrame para no considerarlos en el análisis.
In [14]:
#Cálculo de la cantidad de NaN
Brecha.isnull().sum()
Out[14]:
In [15]:
#Se revisan los nulos o NaN en la tabla informalidad
Informalidad.isnull().sum()
Out[15]:
En este caso lo que haré es eliminar todos los datos NaN de la tabla Brecha, y revisar la cantidad de registros que se tienen por año.
In [16]:
#Se define otra DataFrame sin datos NaN
Brecha=Brecha.dropna()
In [17]:
Brecha.isnull().sum()
Out[17]:
El DataFrame queda sin NaN, ahora lo que falta es explorar cuantos registros quedan por cada año para elegir una muestra anual y luego definir el rango de años que se analizarán o explorarán.
In [18]:
#Visualizo cuantas filas y columnas se tienen por cada año.
for i in range(1995,2015):
print " En el año",i, "se tiene ",Brecha[Brecha['Periodo']==i].shape,"número de filas y columnas, respectivamente."
In [19]:
for i in range(1995,2015):
print " En el año",i, "se tiene ",Informalidad[Informalidad['Periodo']==i].shape,"número de filas y columnas, respectivamente."
Se observa que en la tabla Informalidad se tiene el doble de filas por año, esto debido a que se tienen medidas por género. Elijo para explorar inicialmente los datos en el año 1998 y uso de muestra de datos los correspondientes a los años 2000-2014 para hacer un análisis más detallado.
In [20]:
Informalidad_1998=Informalidad[Informalidad['Periodo']==1998]
In [21]:
#Reviso los primeros 10 registros
Informalidad_1998.head(7)
Out[21]:
Revisando las columnas, se ve que cuatro columnas corresponden a trabajos informales y la última a la población ocupada laboralmente en la entidad, en el género y rango de edades. Con un poco de cuidado, la tabla se muestra como si los datos estuvieran agrupados por año, entidad, género y rango de edad. Entonces lo primero que hago es contruir una columna con el porcentaje que representan las poblaciones en trabajos informales y luego construyo una tabla donde la información sea "desagrupada".
In [23]:
#Se contruye porcentaje de población en trabajos imformales, se agrega una nueva columna. Se usa el método loc[] para operar
#sobre las columnas, para revisar detalles de esto se puede consultar en la libra siguiente
#http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
Valores=np.sum(Informalidad_1998.loc[:,('TAgroInf','TSecInf','TInfSecFor','TDomesInf')],axis=1)
Valores=Valores/Informalidad_1998.loc[:,('Pob_Ocup_T')]
Informalidad_1998.loc[:,'Porcentaje']=Valores
del(Valores)
In [24]:
Informalidad_1998.head()
Out[24]:
In [25]:
#Gráfica por Grupo de Edad
import sys
reload(sys)
sys.setdefaultencoding('utf8') # Lo modifico el encoding del sistema para poder escribir los títulos con acentos.
Informalidad_1998.pivot_table(values='Porcentaje',index=['Grupo_Edad'],columns=['Sexo']).plot(kind='barh',title='Porcentaje de informalidad por Género')
Se observa que para las dos categorías de Hombres y Mujeres, después de los 30 años la media de los porcentajes es casi igual, por otro lado cuando tienen menos de 30 años los hombres se integran a trabajos informales con mayor cantidad.
In [26]:
#Por Género y Entidad Federativa
Informalidad_1998.pivot_table(values='Porcentaje',index=['Entidad'],columns=['Sexo']).plot(kind='bar')
Out[26]:
Es interesante ver como en Coahuila, Colima, Guanajuato, Jalisco, México, Nuevo León y Sonora la población de mujeres trabajan mucho más en informalidad que los hombres.
Agrupando por dos índices, tanto por Género como por grupo de edad, se tienen lo siguiente:
In [27]:
Informalidad_1998.pivot_table(values='Porcentaje',index=['Entidad'],columns=['Sexo','Grupo_Edad']).plot(kind='bar')
Out[27]:
Pese a que se ve medio asobronada la gráfica, se observa que el estado de Cuahuila, Colima, Guanajuato, Jalisco, Nuevo León, Puebla, Sonora y Zacatecas muestran que el grupo de mujeres con edad mayor de 30 años sobre pasan la informalidad de manera muy considerable con respecto a los hombres.
Ahora para ver como se comportan las 4 distribuciones de los indicadores de trabajos informales, hago un histograma para cada una de las variables.
In [28]:
#Las siguientes instrucciones permiten generar una gráfica de los histogramas de las 4 variables
#hago uso de las gráficas "nativas" de pandas para mostrar el ejemplo, pero se pueden correr el
#código de abajo y se obtienen un resultado "similar".
#plt.style.use('bmh')
#plt.hist(Informalidad_1998.TInfSecFor,histtype="stepfilled",bins=15, alpha=0.7, normed=True)
#plt.hist(Informalidad_1998.TSecInf,histtype="stepfilled",bins=15, alpha=0.7, normed=True)
#plt.hist(Informalidad_1998.TAgroInf,histtype="stepfilled",bins=15, alpha=0.7, normed=True)
#plt.hist(Informalidad_1998.TDomesInf,histtype="stepfilled",bins=15, alpha=0.7, normed=True)
#plt.legend(['Trabajo Informal en Sector Formal','Trabajo Sector Informal','Trabajo Agro Informal','Trabajo Doméstico Informal'])
#plt.show()
Informalidad_1998[['TInfSecFor','TSecInf','TAgroInf','TDomesInf']].plot(kind='hist',stacked=True,bins=15,alpha=0.7)
Out[28]:
Se observa que las distribuciones son de "tipo cola pesada", los valores que se muestran en el eje "y" es la frecuencia de los datos. Pero esto deja ver a grandes razgos como se comportan las medidas de los trabajos informales.
Explorando un poco el comportamiento de los datos de la Brecha laborales entre género, eligo los correspondientes al año 1998.
In [29]:
#Se eligen los datos del año 1998 de la Brecha
Brecha_1998=Brecha[Brecha['Periodo']==1998]
In [30]:
#Se visualizan los primeros registros de los datos
Brecha_1998.head()
Out[30]:
Se observa que las dos primeras filas corresponden a los datos Nacionales correspondientes al año 1998, para el análisis elimino esas dos filas.
In [31]:
#Se eliminan las primeras dos lineas o filas para analizados los datos, ya que son el resumen de los datos a nivel nacional.
Brecha_1998=Brecha_1998.iloc[2:,:]
Brecha_1998.head()
Out[31]:
In [32]:
Brecha_1998.pivot_table(values='TNP_M', index=['Entidad'], columns=['Grupo_Edad']).plot(kind='bar')
Out[32]:
Se observa en la gráfica que casi la mitad (17) de las entidades muestran un predominio por la tasa neta de participación femenil en el rango de edad de 15 a 29 años. Por otro lado, algunos estados o entidades muestran una tasa casi igual para las dos categorías.
Cambio la estructura del DataFrame usando la función melt(), esta en ayuda a cambiar la estructura de la tabla de datos es simular a la función melt() del paquete reshape2 de R. La razones de porqué cambiar la estructura de la tabla son diversas, depende mucho de lo que uno esté explorando cómo uno quiere tener la relación entre las variables. En este caso es solo un ejemplo para contruir los boxplot y ver como se comporta la Tasa Neta de parcitipación separada por género.
In [33]:
#Se contruye un nuevo DataFrame
L=pd.melt(Brecha_1998[['Entidad','Grupo_Edad','TNP_M','TNP_H']],id_vars=['Entidad','Grupo_Edad'],var_name='Tasa Neta Participación')
L.head()
Out[33]:
In [34]:
#Cargo otro módulo para no tener problemas con el encoding que se tiene en el sistema
#Se construye el Boxplot para los datos de DataFrame modificado
sns.boxplot(x="Tasa Neta Participación",y="value", data=L)
Out[34]:
Se observa lo radical el la Tasa Neta de Participación separada por género, también se observa que la distribución es asimétrica para los dos tasas. La mediana, la línea negra en medio de la caja, muestra que del 50% al 75% ocupan una área menor de la gráfica (esto es desde la línea intermedia hasta la línea superior).
Lo que por último hago es explorar como se relacionan 4 variables, 2 de las variable de cada tabla. Lo que se revisan son las Tasas Netas para los dos géneros y por otro lado hago una tabla pivot para extraer de la tabla Informalidad los valores del porcentaje separado por género.
In [35]:
#Se contruye un DataFrame partiendo de las columnas de la tabla Brecha_1998
L2=Brecha_1998[['Entidad','Grupo_Edad','TNP_M','TNP_H']]
In [36]:
#Se contruye una tabla pivot para separar los datos del porcentaje por género
L3=Informalidad_1998.pivot_table(values='Porcentaje',index=['Entidad','Grupo_Edad'],columns=['Sexo'])
In [37]:
#Agrego de la tabla L3 los valores del porcentaje en el DataFrame L2
L2['Hombres_Informalidad']=L3['Hombres'].values
L2['Mujeres_Informalidad']=L3['Mujeres'].values
In [38]:
L2.head()
Out[38]:
Se observa que el DataFrame L2 tienen las 4 variables y una más que es el Grupo de Edad, una herramienta gráfica para analizar la posible relación entre las variables es hacer un gráfico scatterplot. El siguiente gráfico es el ejemplo.
In [39]:
#Se genera el scatter plot de las variables
sns.pairplot(L2[["TNP_M","TNP_H","Hombres_Informalidad","Mujeres_Informalidad"]])
Out[39]:
Se observa solo una posible relación lineal entre los datos correspondientes a las tasas de informalidad, esto se observa en las gráficas correspondientes a las variables Hombres_Informalidad vs Mujeres_Informalidad.
Ahora contruyo una DataFrame más, en el cual agrego tanto las variables que se tienen en L2, como un par de variables dummies para representar el Grupo de Edad. La gráfica anterior puede modificarse al considerar el comportamiento de las variables por alguna de las variables dumies.
In [40]:
#Se contruyen el nuevo DataFrame
L4=pd.concat([L2,pd.get_dummies(L2.Grupo_Edad)],axis=1)
L4.columns=['Entidad','Grupo_Edad','TNP_M','TNP_H','Mujeres_Informalidad','Hombres_Informalidad','De_15_a_29','De_30_y_más']
L4.head()
Out[40]:
In [41]:
#Visualización del comportamiento de las variables con respecto al primero grupo de edad
sns.pairplot(L4[["TNP_M","TNP_H","Hombres_Informalidad","Mujeres_Informalidad","De_15_a_29"]],hue="De_15_a_29")
Out[41]:
En la gráfica anterior se logra ver la separación de grupos entre la tasa neta de participación de Hombre y Mujeres, también entre los porcentajes de informalidad entre los dos géneros se visualizan los grupos.
Lo que creo que se puede esperar con una muestra mayor de datos, es que la separación entre las 4 variables sea más notorio, también es posible que se aprecien cambios temporales debido a que la muestra es tomada desde varios años.
Comentario: la exploración solo tienen la intención de mostrar algunas operaciones que se pueden hacer con los DataFrame, como lo obtenido con las funciones concat(), melt() y tablas pivot. También mostrar como contruir o agregar nuevas columnas con datos o cálculos y hacer algunas gráficas con a finalidad de mostrar el comportamiento de las variables con respecto las categorías y las variables entre ellas.